package com.dragon.common.spring.openapi.customizers.operation;

import com.dragon.common.spring.openapi.ApiGroup;
import io.swagger.v3.oas.models.Operation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;

/**
 * @author Chris Chan
 * Create On 2025/10/2 上午11:23
 * Use for: 为Operation添加x-api-group扩展
 * Explain:
 */
@Component
public class GroupMarkOperationCustomizer implements OperationCustomizer {
    private static final Logger log = LoggerFactory.getLogger(GroupMarkOperationCustomizer.class);
    private String group;

    public GroupMarkOperationCustomizer() {
    }

    public GroupMarkOperationCustomizer(String group) {
        this.group = group;
    }

    public static GroupMarkOperationCustomizer of(String group) {
        return new GroupMarkOperationCustomizer(group);
    }

    @Override
    public Operation customize(Operation operation, HandlerMethod handlerMethod) {
        boolean support = isSupportDirect(handlerMethod, group);
        if (support) {
            operation.addExtension("x-api-group", group);
        }
        return operation;
    }

    /**
     * 判断是否支持直接从类获取ApiGroup注解值
     *
     * @param handlerMethod
     * @param group
     * @return
     */
    private boolean isSupportDirect(HandlerMethod handlerMethod, String group) {
        Class<?> beanType = handlerMethod.getBeanType();
        String foundGroup = findApiGroupFromClassDirect(beanType);

        return group.equals(foundGroup);
    }

    /**
     * 从类直接获取ApiGroup注解值
     *
     * @param clazz
     * @return
     */
    private String findApiGroupFromClassDirect(Class<?> clazz) {
        if (clazz.isAnnotationPresent(ApiGroup.class)) {
            return clazz.getAnnotation(ApiGroup.class).value();
        }

        for (Class<?> interfaceClass : clazz.getInterfaces()) {
            if (interfaceClass.isAnnotationPresent(ApiGroup.class)) {
                return interfaceClass.getAnnotation(ApiGroup.class).value();
            }
        }

        Class<?> superclass = clazz.getSuperclass();
        if (superclass != null && superclass != Object.class) {
            String superGroup = findApiGroupFromClassDirect(superclass);
            if (superGroup != null) {
                return superGroup;
            }
        }

        return null;
    }
}
